import java.util.*;
import java.io.IOException;
import java.net.*;

public class DiscoveryServer extends Thread {
	
	public static final int DISC_SERV_PORT = 31234;
	public static final int MAX_PACKET_SIZE = 1500;
	
	private DatagramSocket socket;
	private ArrayList<String> knownPeers;
	
	// SWITCH TO STATIC LATER
	private String UUID;
	private int version;

	public DiscoveryServer(int AEPort, String id, int v) throws UnknownHostException{
        knownPeers = new ArrayList<String>();
        UUID = id;
        version = v;
        
        // start by adding our own address to known peers
        InetAddress addr = InetAddress.getLocalHost();
        byte[] ipAddr = addr.getAddress();
        // convert to dot representation
        String ipAddrStr = "";
        for (int i = 0; i < ipAddr.length; i++) {
            if (i > 0)
                ipAddrStr += ".";
            ipAddrStr += ipAddr[i]&0xFF;
        }
        // add port #
        String local = ipAddrStr + "," + AEPort;
        // add it to knownPeers
        knownPeers.add(local);
        
	}
	
	public void run(){
		try {
			socket = new DatagramSocket(DISC_SERV_PORT);
		
			while (true){
				byte[] buf = new byte[MAX_PACKET_SIZE];
			    DatagramPacket dgPkt = new DatagramPacket( buf, buf.length );
			    socket.receive( dgPkt );
			    String incoming = new String(dgPkt.getData());
			    
			    // only do stuff if it's an AE_REQUEST and it's not from our own 
			    // discovery client
                if (incoming.contains("MessageType:AE_REQUEST") &&
                		( getIpAddress(dgPkt.getAddress()).compareTo(
                         getIpAddress(InetAddress.getLocalHost())) != 0)){
			    	SocketAddress outgoing = dgPkt.getSocketAddress();
			    	
			    	String message = "MessageType:AE_Response\n";
			    	message+= "SourceUUID:" + UUID + "\n";
			    	message+= "ProtocolVersion:" + version + "\n";
			    	message+= "KnownPeers:" + dumpPeers() + "\n";
			    	message+= "EndOfMessage";	
			    	
			    	byte[] out = message.getBytes();
			    	
			    	DatagramPacket outPkt = new DatagramPacket(out, out.length);
			    	outPkt.setSocketAddress(outgoing);
			    	
			    	socket.send(outPkt);
			    }
			    
			}

				
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private String dumpPeers(){
		String s = "";
		for (int i = 0; i < knownPeers.size()-1; i++){
			s += knownPeers.get(i) + "|";
		}
		
		s+= knownPeers.get(knownPeers.size()-1);
		return s;
	}
	
    private String getIpAddress(InetAddress addr) { 
        byte[] ipAddr = addr.getAddress(); 
        // convert to dot representation 
        String ipAddrStr = ""; 
        for (int i = 0; i < ipAddr.length; i++) { 
            if (i > 0) 
                ipAddrStr += "."; 
            ipAddrStr += ipAddr[i]&0xFF; 
        } 
        return ipAddrStr; 
    }
    
}
	

